package api

import (
	"api_gateway/basic/config"
	chat "api_gateway/basic/proto/chat"
	user "api_gateway/handler/api/user"
	"api_gateway/handler/response"
	"api_gateway/untils"
	"encoding/json"
	"github.com/gin-gonic/gin"
	"github.com/gorilla/websocket"
	"log"
	"net/http"
	"strconv"
	"sync"
	"time"
)

// 用户websocket连接映射
var (
	OnlineUser     = make(map[uint]*websocket.Conn)
	onlineUserLock sync.RWMutex
)

// 群聊成员websocket连接映射
var (
	GroupOnlineUser     = make(map[int64]map[uint]*websocket.Conn)
	groupOnlineUserLock sync.RWMutex
)

// WebSocket请求结构
type WSReq struct {
	Cmd  string      `json:"cmd"`  // 命令类型
	Data interface{} `json:"data"` // 请求数据
}

// WebSocket响应结构
type WSResp struct {
	Code uint        `json:"code"` // 状态码
	Msg  string      `json:"msg"`  // 消息说明
	Data interface{} `json:"data"` // 响应数据
}

// 发送消息结构
type SendS struct {
	FormUserId  uint   `json:"form_user_id"` // 发送者ID
	ToTargetId  uint   `json:"to_target_id"` // 接收方ID（私聊）/ 群ID（群聊）
	Content     string `json:"content"`      // 消息内容
	MessageType int64  `json:"message_type"` // 消息类型
}

// 私聊请求结构
type WSSendReq struct {
	Cmd  string `json:"cmd"`  // 命令类型
	Data SendS  `json:"data"` // 发送数据
}

// 群聊消息结构
type GroupS struct {
	GroupId     string `json:"group_id"`     // 群id
	SenderId    int64  `json:"sender_id"`    // 发送人id
	Content     string `json:"content"`      // 群发消息内容
	MessageType int64  `json:"message_type"` // 消息类型
}

// 群聊请求结构
type WSGroupReq struct {
	Cmd  string `json:"cmd"`  // 命令类型
	Data GroupS `json:"data"` // 群发数据
}

// 聊天WebSocket处理函数
func Chat(c *gin.Context) {
	//// 从中间件获取用户ID
	//userId := c.GetUint("userId")

	// 获取用户参数
	userIdStr, _ := c.GetQuery("userId")
	if userIdStr == "" {
		response.Error(c, -1, "缺少用户ID参数", nil)
		log.Println("缺少用户ID参数")
		return
	}
	userIdInt, _ := strconv.Atoi(userIdStr)
	if userIdInt <= 0 {
		response.Error(c, -1, "无效的用户ID", nil)
		log.Println("无效的用户ID")
		return
	}
	userId := uint(userIdInt)

	// 检查用户是否已在线
	if _, exists := OnlineUser[userId]; exists {
		response.Error(c, -1, "用户已在其他设备登录", nil)
		log.Println("用户已在其他设备登录")
		return
	}

	// 配置WebSocket升级器
	var upgrader = websocket.Upgrader{
		CheckOrigin: func(r *http.Request) bool {
			return true // 允许任何来源的连接
		},
	} // 使用默认选项

	// 升级到WebSocket连接
	conn, err := upgrader.Upgrade(c.Writer, c.Request, nil)
	if err != nil {
		log.Print("升级WebSocket连接失败:", err)
		response.Error(c, -1, "WebSocket连接失败", nil)
		return
	}

	// 在线用户数据管理
	OnlineUser[userId] = conn
	user.AddOnlineUser(userId, conn)

	log.Printf("用户 %d 已上线，当前在线用户数 %d", userId, len(OnlineUser))

	// 用户上线时从redis获取离线消息推送给用户
	go PushOfflineMessagesOnUserLogin(userId, conn)

	// 用户上线时加入所有所属群聊
	go joinUserGroups(userId, conn)

	// 确保连接关闭时清理资源
	defer func() {
		user.RemoveOnlineUser(userId)
		delete(OnlineUser, userId)
		conn.Close()
		log.Printf("用户 %d 已下线，当前在线用户数: %d", userId, len(OnlineUser))
	}()

	// 心跳检测协程
	go func() {
		// 每30秒发送一次心跳
		for {
			err = conn.WriteMessage(websocket.PingMessage, []byte{})
			if err != nil {
				return
			}

			time.Sleep(30 * time.Second)
		}
	}()

	// 消息处理循环
	for {
		_, message, err := conn.ReadMessage()
		if err != nil {
			log.Printf("用户 %d 连接断开: %v", userId, err)
			break
		}

		var req WSReq

		err = json.Unmarshal(message, &req)
		if err != nil {
			WSRespErr(conn, 1000, "非法的JSON格式")
			continue
		}

		// 根据命令类型分发处理
		switch req.Cmd {
		case "send":
			go Send(conn, message, userId)
		case "sendGroup":
			go SendGroup(conn, message, userId)
		default:
			WSRespErr(conn, 10001, "未找到对应功能")
		}
	}
}

// 群发消息处理函数
func SendGroup(conn *websocket.Conn, message []byte, userId uint) {
	var req WSGroupReq
	err := json.Unmarshal(message, &req)
	if err != nil {
		WSRespErr(conn, 30001, "解析群聊消息失败")
		return
	}

	if req.Data.GroupId == "" {
		WSRespErr(conn, 30002, "缺少群ID参数")
		return
	}

	if req.Data.Content == "" {
		WSRespErr(conn, 30003, "缺少群聊消息参数")
		return
	}

	// 将群ID转换为int64
	groupID, err := strconv.ParseInt(req.Data.GroupId, 10, 64)
	if err != nil {
		WSRespErr(conn, 30004, "群ID格式错误")
		return
	}

	senderId := userId

	// 构建群聊消息
	groupMsg := &chat.SendGroupMessageReq{
		GroupId:     req.Data.GroupId,
		SenderId:    int64(senderId),
		Content:     req.Data.Content,
		MessageType: req.Data.MessageType,
	}
	log.Printf("用户 %d 发送群消息到群 %s: %s", userId, req.Data.GroupId, req.Data.Content)

	// 异步保存至群聊消息队列
	rabbitmq := untils.NewRabbitMQSimple(config.GROUP_CHAT)
	// 将消息序列化为Json格式
	marshal, _ := json.Marshal(groupMsg)
	simple, err := rabbitmq.PublishSimple(string(marshal))
	if err != nil || !simple {
		log.Printf("群聊消息推送失败: %v", err)
		WSRespErr(conn, 30006, "群聊消息推送失败")
		return
	}

	// 向群内在线成员广播消息
	broadcastToGroupMembers(groupID, map[string]interface{}{
		"groupId":     req.Data.GroupId,
		"senderId":    userId,
		"content":     req.Data.Content,
		"messageType": req.Data.MessageType,
		"timestamp":   time.Now().Unix(),
	}, userId)
	WSRespSuccess(conn, "群消息发送成功")
}

// 私聊消息处理函数
func Send(conn *websocket.Conn, message []byte, userId uint) {
	// 验证参数
	var req WSSendReq
	err := json.Unmarshal(message, &req)
	if err != nil {
		WSRespErr(conn, 20001, "解析JSON失败")
		return
	}

	if req.Data.ToTargetId < 1 {
		WSRespErr(conn, 20002, "缺少接收用户ID参数")
		return
	}

	if req.Data.Content == "" {
		WSRespErr(conn, 20004, "缺少消息内容参数")
		return
	}

	private := &chat.SendMessageReq{
		FormUserId:  int64(req.Data.FormUserId),
		ToTargetId:  int64(req.Data.ToTargetId),
		Content:     req.Data.Content,
		MessageType: req.Data.MessageType,
	}

	// 检查目标用户是否在线
	if OnlineUser[req.Data.ToTargetId] == nil {
		// 异步保存通讯信息到离线私聊消息队列
		rabbitmq := untils.NewRabbitMQSimple(config.PRIVATE_OFFLINE) //离线私聊交换机
		// 将信息序列化为Json格式
		marshal, _ := json.Marshal(private)
		simple, err := rabbitmq.PublishSimple(string(marshal))
		if err != nil || !simple {
			log.Printf("通讯信息推送失败: %v", err)
			WSRespErr(conn, 20006, "通讯信息推送失败")
			return
		}

		WSRespErr(conn, 20003, "目标用户不在线,已推送至离线私聊队列")
		return
	}

	// 异步保存通讯信息到私聊消息队列
	rabbitmq := untils.NewRabbitMQSimple(config.PRIVATE_CHAT) //私聊交换机
	// 将信息序列化为Json格式
	marshal, _ := json.Marshal(private)
	simple, err := rabbitmq.PublishSimple(string(marshal))
	if err != nil || !simple {
		log.Printf("通讯信息推送失败: %v", err)
		WSRespErr(conn, 20006, "通讯信息推送失败")
		return
	}
	log.Println("通讯信息推送队列成功")

	// 向目标用户发送消息
	WSRespSuccess(OnlineUser[req.Data.ToTargetId], req.Data.Content)

	// 向发送者返回成功响应
	WSRespSuccess(conn, "发送成功")

}

// WebSocket错误响应函数
func WSRespErr(conn *websocket.Conn, code uint, msg string) {
	response := WSResp{
		Code: code,
		Msg:  msg,
		Data: nil,
	}

	responseStr, _ := json.Marshal(response)

	err := conn.WriteMessage(websocket.TextMessage, responseStr)
	if err != nil {
		log.Println("写入消息错误:", err)
	}
}

// WebSocket成功响应函数
func WSRespSuccess(conn *websocket.Conn, data interface{}) {
	response := WSResp{
		Code: http.StatusOK,
		Msg:  "成功",
		Data: data,
	}

	responseStr, _ := json.Marshal(response)

	err := conn.WriteMessage(websocket.TextMessage, responseStr)
	if err != nil {
		log.Println("写入消息错误:", err)
	}
}
